"""
学生信息管理系统 - 数据库模块 (数据访问层)

📚 教学目标：
1. 理解数据持久化的概念
2. 学习SQLite数据库的基本操作
3. 掌握数据库连接管理
4. 了解SQL语句的编写

🎯 本模块在项目中的作用：
- 负责数据库的创建和初始化
- 管理数据库连接
- 提供数据访问的基础设施
- 封装底层数据库操作

⭐ 学习顺序：【第2步】- 在学习完student.py后学习此模块

🔗 模块依赖关系：
- 被依赖：service.py 依赖此模块
- 依赖项：无直接依赖（只使用Python标准库）

💡 设计原则：
- 单一职责：只负责数据库相关操作
- 封装性：隐藏数据库实现细节
- 可复用：提供通用的数据库连接方法
"""

import sqlite3  # 💡 Python标准库，无需额外安装
import os       # 💡 用于文件和系统操作


class StudentDatabase:
    """
    学生数据库管理类
    
    🎓 教学要点：
    - 类的封装：将数据库操作封装在类中
    - 构造函数：初始化数据库连接
    - 实例变量：存储数据库文件名
    - 方法设计：每个方法负责特定的数据库操作
    
    💡 设计模式：
    - 工厂模式：提供统一的数据库连接创建方法
    - 单例模式思想：虽然不是严格的单例，但管理统一的数据库文件
    """
    
    def __init__(self, db_name="students.db"):
        """
        初始化数据库连接
        
        🎓 教学要点：
        - 默认参数的使用：db_name="students.db"
        - 立即初始化：在创建对象时就创建数据库表
        - 职责分离：构造函数只负责初始化，具体创建逻辑在init_database()中
        
        :param db_name: 数据库文件名，默认为"students.db"
        """
        self.db_name = db_name  # 💡 保存数据库文件名，后续操作都会用到
        self.init_database()    # 💡 立即初始化数据库表结构

    def init_database(self):
        """
        创建学生信息表
        
        🎓 教学要点：
        - SQL DDL语句：CREATE TABLE的使用
        - 数据类型：INTEGER、TEXT、TIMESTAMP
        - 约束条件：PRIMARY KEY、UNIQUE、NOT NULL、DEFAULT
        - 事务管理：commit()和close()的重要性
        - 异常安全：确保数据库连接最终会被关闭
        
        💡 数据库设计要点：
        1. id：主键，自动递增，用于内部标识
        2. student_id：学号，唯一约束，业务主键
        3. NOT NULL约束：确保必填字段不为空
        4. DEFAULT CURRENT_TIMESTAMP：自动记录创建时间
        
        🔍 SQL语句解析：
        - CREATE TABLE IF NOT EXISTS：如果表不存在则创建
        - INTEGER PRIMARY KEY AUTOINCREMENT：自增主键
        - TEXT UNIQUE NOT NULL：唯一且非空的文本字段
        - TIMESTAMP DEFAULT CURRENT_TIMESTAMP：默认当前时间戳
        """
        conn = sqlite3.connect(self.db_name)  # 💡 创建数据库连接
        cursor = conn.cursor()                # 💡 创建游标对象，用于执行SQL语句

        # 💡 创建学生信息表，使用多行字符串提高可读性
        cursor.execute('''
                       CREATE TABLE IF NOT EXISTS students
                       (
                           id           INTEGER PRIMARY KEY AUTOINCREMENT,  -- 主键，自动递增
                           student_id   TEXT UNIQUE NOT NULL,               -- 学号，唯一约束
                           name         TEXT        NOT NULL,               -- 姓名，必填
                           age          INTEGER     NOT NULL,               -- 年龄，必填
                           gender       TEXT        NOT NULL,               -- 性别，必填
                           major        TEXT        NOT NULL,               -- 专业，必填
                           class_name   TEXT        NOT NULL,               -- 班级，必填
                           phone        TEXT,                               -- 电话，可选
                           email        TEXT,                               -- 邮箱，可选
                           created_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 创建时间，自动生成
                       )
                       ''')

        conn.commit()  # 💡 提交事务，确保更改被保存
        conn.close()   # 💡 关闭连接，释放资源
        print("数据库初始化完成！")  # 💡 给用户反馈

    def get_connection(self):
        """
        获取数据库连接
        
        🎓 教学要点：
        - 工厂方法模式：统一创建数据库连接的方法
        - 代码复用：避免在多处重复写连接代码
        - 接口设计：提供简洁的API给调用者
        - 错误处理：虽然这里没有显式处理，但sqlite3.connect()会抛出异常
        
        💡 设计考虑：
        - 每次返回新连接，避免连接冲突
        - 调用者负责关闭连接，明确职责分工
        - 支持多线程使用（SQLite的连接不能跨线程共享）
        
        :return: SQLite数据库连接对象
        """
        return sqlite3.connect(self.db_name)  # 💡 返回新的数据库连接

    def close_connection(self, conn):
        """
        关闭数据库连接

        🎓 教学要点：
        - 资源管理：及时释放数据库连接资源
        - 防御性编程：检查连接是否存在再关闭
        - 最佳实践：配对使用get_connection()和close_connection()
        - 异常安全：避免因连接已关闭而出错

        💡 为什么需要单独的关闭方法：
        1. 统一的资源管理风格
        2. 便于添加额外的清理逻辑
        3. 提高代码的可读性
        4. 为将来扩展做准备（如连接池）

        :param conn: 要关闭的数据库连接对象
        """
        if conn:  # 💡 防御性编程：确保连接对象存在
            conn.close()  # 💡 关闭数据库连接，释放资源


# 示例用法
if __name__ == "__main__":
    db = StudentDatabase()  # 创建数据库管理对象
    if not os.path.exists(db.db_name):  # 检查数据库文件是否存在
        print("数据库文件不存在，正在创建...")
        db.init_database()
        print("数据库文件创建成功！")
    else:
        print("数据库文件已存在，无需创建。")
    conn = db.get_connection()  # 获取数据库连接
    # 在这里可以执行其他数据库操作，如添加学生等
    # 例如：conn.execute("SELECT * FROM students")  # 执行查询操作
    if conn:
        print("数据库连接获取成功！")
        # 关闭连接
        db.close_connection(conn)
        print("数据库连接已关闭。")